package org.gikolet.guice.db;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import com.google.inject.Inject;

public final class TransactionProxy<T> implements InvocationHandler {

	private T t;

	@Inject
	private TransactionManager transactionManager;

	public TransactionProxy(TransactionManager transactionManager, T obj) {
		this.transactionManager = transactionManager;
		this.t = obj;
	}

	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		Object result;

		boolean inTransaction = false;

		try {
			if (method.getAnnotation(Transactional.class) != null) {
				inTransaction = this.transactionManager.inTransaction();
			}

			if (!inTransaction) {
				this.transactionManager.beginTransaction();
			}

			System.out
					.println("--------------------- before method ---------------------");

			result = method.invoke(t, args);

			System.out
					.println("--------------------- after method ---------------------");

			if (!inTransaction) {
				this.transactionManager.setTransactionSuccessful();
			}

			return result;

		} catch (InvocationTargetException e) {

			throw e.getTargetException();

		} catch (Throwable e) {

			throw e;

		} finally {
			if (!inTransaction) {
				this.transactionManager.endTransaction();
			}
		}
	}
}
